From 42217cbc5b3e84b8c145d8cfb62dd5de0134b9e8 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Wed, 24 Nov 2004 11:34:32 +0000 Subject: [PATCH] bitkeeper revision 1.1159.187.4 (41a471c8NjyQJy-vepqpb8H7LdzHzA) Allow preemption of long-running hypercalls for softirq processing. --- xen/arch/x86/domain.c | 16 ++++++++++++++++ xen/arch/x86/memory.c | 5 ++++- xen/arch/x86/traps.c | 2 ++ xen/arch/x86/x86_32/entry.S | 16 ++++++++++++++++ xen/common/dom_mem_ops.c | 12 ++++++++++++ xen/common/grant_table.c | 3 +++ xen/include/xen/irq_cpustat.h | 3 ++- xen/include/xen/sched.h | 9 +++++++++ 8 files changed, 64 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 69e1506a02..77a39a2a97 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -426,6 +426,22 @@ long do_iopl(domid_t domain, unsigned int new_io_pl) return 0; } +void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...) +{ + execution_context_t *ec = get_execution_context(); + unsigned long *preg = &ec->ebx; + unsigned int i; + va_list args; + + ec->eax = op; + ec->eip -= 2; /* re-execute 'int 0x82' */ + + va_start(args, nr_args); + for ( i = 0; i < nr_args; i++ ) + *preg++ = va_arg(args, unsigned long); + va_end(args); +} + #endif diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index 0a15601bf4..c6d9951bc5 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -1300,6 +1300,9 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) for ( i = 0; i < count; i++ ) { + hypercall_may_preempt( + __HYPERVISOR_mmu_update, 3, ureqs, count-i, success_count); + if ( unlikely(__copy_from_user(&req, ureqs, sizeof(req)) != 0) ) { MEM_LOG("Bad __copy_from_user"); @@ -1455,7 +1458,7 @@ int do_mmu_update(mmu_update_t *ureqs, int count, int *success_count) } if ( unlikely(success_count != NULL) ) - put_user(count, success_count); + put_user(i, success_count); return rc; } diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index f5fb6618d3..3a8f8cdd15 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -804,6 +804,8 @@ long do_set_trap_table(trap_info_t *traps) for ( ; ; ) { + hypercall_may_preempt(__HYPERVISOR_set_trap_table, 1, traps); + if ( copy_from_user(&cur, traps, sizeof(cur)) ) return -EFAULT; if ( cur.address == 0 ) break; diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 6b6376e8bc..c92090a141 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -95,6 +95,11 @@ do_multicall: jnc bad_multicall_address multicall_loop: pushl %ecx + movl 4(%esp),%ecx # %ecx = struct domain + movl DOMAIN_processor(%ecx),%eax + shl $6,%eax # sizeof(irq_cpustat) == 64 + testl $~0,SYMBOL_NAME(irq_stat)(%eax,1) + jnz multicall_preempt multicall_fault1: pushl 20(%ebx) # args[4] multicall_fault2: @@ -120,6 +125,17 @@ multicall_fault7: xorl %eax,%eax jmp ret_from_hypercall +multicall_preempt: + # NB. remaining nr_calls is already at top of stack + pushl %ebx # call_list + pushl $2 # nr_args == 2 + pushl $__HYPERVISOR_multicall # op == __HYPERVISOR_multicall + call hypercall_create_continuation + addl $16,%esp + popl %ebx + movl $__HYPERVISOR_multicall,%eax + jmp ret_from_hypercall + bad_multicall_address: popl %ebx movl $-EFAULT,%eax diff --git a/xen/common/dom_mem_ops.c b/xen/common/dom_mem_ops.c index 2169fad2a1..8e9a9e97e1 100644 --- a/xen/common/dom_mem_ops.c +++ b/xen/common/dom_mem_ops.c @@ -35,6 +35,12 @@ static long alloc_dom_mem(struct domain *d, for ( i = 0; i < nr_extents; i++ ) { + hypercall_may_preempt( + __HYPERVISOR_dom_mem_op, 5, + MEMOP_increase_reservation, + &extent_list[i], nr_extents-i, extent_order, + (d == current) ? DOMID_SELF : d->id); + if ( unlikely((page = alloc_domheap_pages(d, extent_order)) == NULL) ) { DPRINTK("Could not allocate a frame\n"); @@ -63,6 +69,12 @@ static long free_dom_mem(struct domain *d, for ( i = 0; i < nr_extents; i++ ) { + hypercall_may_preempt( + __HYPERVISOR_dom_mem_op, 5, + MEMOP_decrease_reservation, + &extent_list[i], nr_extents-i, extent_order, + (d == current) ? DOMID_SELF : d->id); + if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) ) return i; diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 2c948b7433..e01cad9e80 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -437,6 +437,9 @@ do_grant_table_op( { long rc; + /* XXX stubbed out XXX */ + return -ENOSYS; + if ( count > 512 ) return -EINVAL; diff --git a/xen/include/xen/irq_cpustat.h b/xen/include/xen/irq_cpustat.h index 075f55bf29..9d09ad3fb8 100644 --- a/xen/include/xen/irq_cpustat.h +++ b/xen/include/xen/irq_cpustat.h @@ -10,6 +10,7 @@ */ #include +#include /* * Simple wrappers reducing source bloat. Define all irq_stat fields @@ -17,7 +18,7 @@ * definitions instead of differing sets for each arch. */ -extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */ +extern irq_cpustat_t irq_stat[]; #ifdef CONFIG_SMP #define __IRQ_STAT(cpu, member) (irq_stat[cpu].member) diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 970a27c56b..a67547e6b9 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -21,6 +21,7 @@ #include #include #include +#include extern unsigned long volatile jiffies; extern rwlock_t domlist_lock; @@ -217,6 +218,14 @@ void continue_cpu_idle_loop(void); void continue_nonidle_task(void); +void hypercall_create_continuation(unsigned int op, unsigned int nr_args, ...); +#define hypercall_may_preempt(_op, _nr_args, _args...) \ + do { \ + if ( unlikely(softirq_pending(smp_processor_id())) ) { \ + hypercall_create_continuation(_op , _nr_args , ##_args); \ + return _op; \ + } } while ( 0 ) + /* This domain_hash and domain_list are protected by the domlist_lock. */ #define DOMAIN_HASH_SIZE 256 #define DOMAIN_HASH(_id) ((int)(_id)&(DOMAIN_HASH_SIZE-1)) -- 2.30.2